home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
EnigmA Amiga Run 1996 February
/
EnigmA AMIGA RUN 04 (1996)(G.R. Edizioni)(IT)[!][issue 1996-02][Skylink CD III].iso
/
earcd
/
comm2
/
kms20src.lha
/
KMSAM
/
kmsam.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-09-24
|
76KB
|
2,652 lines
/*************************************************************************
*
* Copyright (C) 1995 Thomas Schwarz
* <kmshq@ruatha.muc.de>
* <Schwarz.Thomas@fhm.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*************************************************************************/
#include "KMSAM.h"
#include <KMS/KMS_def.h>
/* Defines */
#define VERSION "1.27"
#define MID_ADD 1
#define MID_REMOVE 2
#define MID_UP 3
#define MID_DOWN 4
#define MID_SORT 5
#define MID_EDIT 6
#define MID_OK 7
#define MID_ABOUT 8
#define MID_DOUBLE 9
#define MID_PARENT 10
#define MID_CHILD 11
#define MID_PATH 12
#define MID_SELAREA 13
#define MID_CUT 14
#define MID_COPY 15
#define MID_PASTE 16
#define EID_USE 20
#define EID_CANCEL 21
#define EID_SELAB 22
#define EID_NAMEAB 23
#define EID_CGTYPE 24
/* Escape Sequences */
#define eR "\033r"
#define eC "\033c"
#define eL "\033l"
#define eN "\033n"
#define eB "\033b"
#define eI "\033i"
#define ePB "\0332"
#define ePW "\0338"
/* Prototypes */
int main(int, char **);
LONG DisplayDir(struct AreaNode *, struct AreaNode *);
BOOL ReadAreaList(VOID);
BOOL WriteAreaList(VOID);
BOOL InitAreaFile(VOID);
struct AreaNode *AddAN(VOID);
VOID DeleteAN(struct AreaNode *);
BOOL ParseArgs(VOID);
VOID Sense(APTR, STRPTR);
VOID ReadAccBits(VOID);
BOOL WriteAccBits(VOID);
struct AreaNode *SetArea(UWORD);
struct AreaNode *ResolvePath(STRPTR);
STRPTR PathParse(STRPTR, STRPTR);
struct AreaNode *SeekAreaName(struct AreaNode *, STRPTR);
struct AreaNode *AreaSearch(STRPTR);
LONG InsertArea(struct AreaNode *);
VOID RemoveArea(struct AreaNode *);
VOID CleanUpAreaList(VOID);
struct KMSBase *GetKMSBase(VOID);
VOID CreatePath(STRPTR);
VOID UpdatePath(VOID);
VOID Upper(STRPTR);
VOID Error(STRPTR);
VOID TakeASem(BOOL);
VOID DropASem(VOID);
VOID TakeMSem(BOOL);
VOID DropMSem(VOID);
/* Hooks */
SAVEDS ASM LONG list_dspfunc(
REG(a0) struct Hook *hook,
REG(a2) char **array,
REG(a1) struct AreaNode *area)
{
if (area)
*array = area->AreaData.Name;
else
*array = NULL;
return 0;
}
static struct Hook list_dsphook = {
{NULL, NULL},
(VOID *)list_dspfunc,
NULL, NULL
};
SAVEDS ASM LONG list_cmpfunc(
REG(a0) struct Hook *hook,
REG(a1) struct AreaNode *area1,
REG(a2) struct AreaNode *area2)
{
if (area1 && area2)
return stricmp(area1->AreaData.Name, area2->AreaData.Name);
else
return 0;
}
static struct Hook list_cmphook =
{
{NULL, NULL},
(VOID *)list_cmpfunc,
NULL, NULL
};
/* Vars */
static Object *App ; /* Application object */
static Object *WI_Manager; /* Main Window object */
static Object *WI_Editor ; /* Editor Window object */
static Object *LV_Areas ; /* Areas Listview object */
static Object *LV_AccBits; /* AccBits Listview object */
static Object *BT_Parent ; /* Parent Button object */
static Object *BT_Child ; /* Child Button object */
static Object *BT_Add ; /* Add Button object */
static Object *BT_Remove ; /* Remove Button object */
static Object *BT_Up ; /* Up Button object */
static Object *BT_Down ; /* Down Button object */
static Object *BT_Sort ; /* Sort Button object */
static Object *BT_Edit ; /* Edit Button object */
static Object *BT_Cut ; /* Cut Button object */
static Object *BT_Copy ; /* Copy Button object */
static Object *BT_Paste ; /* Paste Button object */
static Object *BT_EUse ; /* Edit-Use Button object */
static Object *BT_ECancel ; /* Edit-Cancel Button object */
/* String-Gadget objects */
static Object *ST_Name;
static Object *ST_Info;
static Object *ST_MBName;
static Object *ST_FilePath;
static Object *ST_AccBit;
static Object *ST_QuoteStr;
static Object *ST_PQuoteStr;
static Object *ST_ResendStr;
static Object *ST_ForwardStr;
static Object *ST_OriginStr;
static Object *ST_Path;
static Object *ST_HoldNum;
static Object *ST_HoldDays;
/* Slider objects */
static Object *SL_RLevel;
static Object *SL_WLevel;
static Object *SL_ELevel;
/* Cycle objects */
static Object *CY_ATypeRoot;
static Object *CY_ATypePublic;
static const char *CYA_ATypeRoot[] =
{
"Mail",
NULL
};
static const char *CYA_ATypePublic[] =
{
"News",
"Binary",
NULL
};
/* CheckMark objects */
static Object *CH_Group;
static Object *CH_ToName;
static Object *CH_NoRe;
static Object *CH_Pseudos;
/* Page object */
static Object *PG_AType;
/* Menü */
static const struct NewMenu MenuList[] =
{
{NM_TITLE, "Project", 0, 0, 0, 0},
{NM_ITEM, "About...", "?", 0, 0, (APTR)MID_ABOUT},
{NM_ITEM, NM_BARLABEL, 0, 0, 0, 0},
{NM_ITEM, "Quit", "Q", 0, 0, (APTR)MID_OK},
{NM_END, NULL, 0, 0, 0, 0}
};
/* Misc */
STRPTR Areaname = NULL;
struct AreaNode *CurrentArea = NULL;
struct AreaNode *CurrentMother = NULL;
struct Library *UMSBase = NULL;
UMSUserAccount SysUMSAccount = NULL;
ULONG SystemStartups;
TEXT AccBitNames[32][LEN_ACCBITNAME+1];
TEXT PathString[LEN_KMSPATH+1];
struct Area AreaStore; /* Paste-Puffer */
struct KMSBase *KMSBase = NULL;
/* Hauptprogramm */
/// "main"
int main(int argc, char *argv[])
{
struct AreaNode *an, *an2, *an3;
struct Area area;
BOOL running = TRUE, addflag = FALSE;
BOOL areaschanged = FALSE, bitschanged = FALSE;
BOOL cut = FALSE, error = FALSE;
ULONG signal, acc;
LONG num, entries, state, index;
UWORD idmerk;
AreaStore.ID = 0;
App = NULL;
init();
if (!ParseArgs())
Sense(App, NULL);
if (!GetKMSBase())
Sense(App, NULL);
App = ApplicationObject,
MUIA_Application_Title , "KMS Area Manager",
MUIA_Application_Version , "$VER: KMSAM " VERSION " (" __COMMODORE_DATE__ ")",
MUIA_Application_Copyright , "©1994 Thomas Schwarz",
MUIA_Application_Author , "Thomas Schwarz",
MUIA_Application_Description, "Manages Karfunkel Mailbox System Msg-Areas.",
MUIA_Application_Base , "KMSAM",
MUIA_Application_Menu , MenuList,
MUIA_Application_SingleTask , TRUE,
SubWindow, WI_Manager = WindowObject,
MUIA_Window_ID, MAKE_ID('M','A','I','N'),
MUIA_Window_Title, "KMS Area Manager",
WindowContents, VGroup,
Child, HGroup,
Child, VGroup,
GroupFrameT("Areas"),
/*
Child, ST_Path = StringObject,
StringFrame,
MUIA_String_Reject, " ",
MUIA_String_MaxLen, LEN_KMSPATH+1,
End,
*/
Child, ST_Path = TextObject,
StringFrame,
End,
Child, LV_Areas = ListviewObject,
MUIA_Listview_List, ListObject,
InputListFrame,
MUIA_List_DisplayHook, &list_dsphook,
MUIA_List_CompareHook, &list_cmphook,
End,
End,
Child, HGroup,
MUIA_Group_SameSize, TRUE,
Child, BT_Parent = KeyButton("Parent", 'p'),
Child, HSpace(0),
Child, BT_Child = KeyButton("Children", 'c'),
End,
End,
Child, VGroup,
MUIA_Weight, 25,
Child, VGroup,
GroupFrameT("Menu"),
Child, BT_Cut = KeyButton("Cut" , 't'),
Child, BT_Copy = KeyButton("Copy" , 'o'),
Child, BT_Paste = KeyButton("Paste" , 'a'),
End,
Child, VGroup,
GroupFrame,
Child, BT_Add = KeyButton("Insert", 'i'),
Child, BT_Remove = KeyButton("Delete", 'l'),
End,
Child, VGroup,
GroupFrame,
Child, BT_Up = KeyButton("Up" , 'u'),
Child, BT_Down = KeyButton("Down" , 'd'),
End,
Child, VGroup,
GroupFrame,
Child, BT_Sort = KeyButton("Sort" , 's'),
End,
Child, VGroup,
GroupFrame,
Child, BT_Edit = KeyButton("Edit" , 'e'),
End,
End,
End,
End,
End,
SubWindow, WI_Editor = WindowObject,
MUIA_Window_ID, MAKE_ID('E','D','I','T'),
MUIA_Window_Title, "KMS Area Editor",
WindowContents, VGroup,
Child, HGroup,
Child, VGroup,
Child, ColGroup(2),
Child, KeyLabel2("Area Name:", 'n'),
Child, ST_Name = StringObject,
StringFrame,
MUIA_String_MaxLen, LEN_AREANAME+1,
MUIA_ControlChar, 'n',
End,
Child, KeyLabel2("Area Info:", 'i'),
Child, ST_Info = StringObject,
StringFrame,
MUIA_String_MaxLen, LEN_AREAINFO+1,
MUIA_ControlChar, 'i',
End,
Child, KeyLabel2("UMS Group:", 'g'),
Child, ST_MBName = StringObject,
StringFrame,
MUIA_String_MaxLen, LEN_MBNAME+1,
MUIA_ControlChar, 'g',
End,
Child, KeyLabel2("Binary Path:", 'b'),
Child, ST_FilePath = StringObject,
StringFrame,
MUIA_String_MaxLen, LEN_FILEAREA+1,
MUIA_ControlChar, 'b',
End,
End,
Child, HGroup,
Child, Label2("HoldNum:"),
Child, ST_HoldNum = StringObject,
StringFrame,
MUIA_String_MaxLen, 5,
MUIA_String_Accept, "0123456789",
MUIA_String_Integer, 0,
End,
Child, Label2("HoldDays:"),
Child, ST_HoldDays = StringObject,
StringFrame,
MUIA_String_MaxLen, 5,
MUIA_String_Accept, "0123456789",
MUIA_String_Integer, 0,
End,
End,
Child, VSpace(0),
Child, HGroup,
Child, HSpace(0),
Child, ColGroup(2),
Child, Label1("Group:"),
Child, CH_Group = CheckMark(FALSE),
Child, Label1("To:"),
Child, CH_ToName = CheckMark(FALSE),
End,
Child, HSpace(0),
Child, ColGroup(2),
Child, Label1("Re:"),
Child, CH_NoRe = CheckMark(FALSE),
Child, Label1("Pseudos:"),
Child, CH_Pseudos = CheckMark(FALSE),
End,
Child, HSpace(0),
End,
Child, VSpace(0),
Child, ColGroup(2),
Child, KeyLabel2("Type:", 't'),
Child, PG_AType = PageGroup,
Child, CY_ATypeRoot = CycleObject,
MUIA_Cycle_Entries, CYA_ATypeRoot,
MUIA_ControlChar, 't',
End,
Child, CY_ATypePublic = CycleObject,
MUIA_Cycle_Entries, CYA_ATypePublic,
MUIA_ControlChar, 't',
End,
End,
End,
Child, VSpace(0),
End,
Child, HSpace(10),
Child, VGroup,
Child, ColGroup(2),
GroupFrameT("Access Levels"),
Child, Label2("Read:"),
Child, SL_RLevel = SliderObject,
MUIA_Group_Horiz , TRUE,
MUIA_Slider_Min , 0,
MUIA_Slider_Max , 255,
MUIA_Slider_Level, 0,
End,
Child, Label2("Write:"),
Child, SL_WLevel = SliderObject,
MUIA_Group_Horiz , TRUE,
MUIA_Slider_Min , 0,
MUIA_Slider_Max , 255,
MUIA_Slider_Level, 0,
End,
Child, Label2("Edit:"),
Child, SL_ELevel = SliderObject,
MUIA_Group_Horiz , TRUE,
MUIA_Slider_Min , 0,
MUIA_Slider_Max , 255,
MUIA_Slider_Level, 0,
End,
End,
Child, VGroup,
GroupFrameT("Access Bits"),
Child, LV_AccBits = ListviewObject,
MUIA_Listview_MultiSelect, TRUE,
MUIA_Listview_List, ListObject,
InputListFrame,
End,
End,
Child, ST_AccBit = StringObject,
StringFrame,
MUIA_String_Reject, " ",
MUIA_String_MaxLen, LEN_ACCBITNAME+1,
MUIA_String_AttachedList, LV_AccBits,
End,
End,
End,
End,
Child, HGroup,
Child, HSpace(0),
Child, HSpace(0),
End,
Child, ColGroup(4),
Child, Label1("Quote:"),
Child, ST_QuoteStr = StringObject,
StringFrame,
MUIA_String_MaxLen, 3,
MUIA_String_Accept, "0123456789",
MUIA_String_Integer, 0,
End,
Child, Label1("PQuote:"),
Child, ST_PQuoteStr = StringObject,
StringFrame,
MUIA_String_MaxLen, 3,
MUIA_String_Accept, "0123456789",
MUIA_String_Integer, 0,
End,
Child, Label1("Resend:"),
Child, ST_ResendStr = StringObject,
StringFrame,
MUIA_String_MaxLen, 3,
MUIA_String_Accept, "0123456789",
MUIA_String_Integer, 0,
End,
Child, Label1("Forward:"),
Child, ST_ForwardStr = StringObject,
StringFrame,
MUIA_String_MaxLen, 3,
MUIA_String_Accept, "0123456789",
MUIA_String_Integer, 0,
End,
Child, Label1("Origin:"),
Child, ST_OriginStr = StringObject,
StringFrame,
MUIA_String_MaxLen, 3,
MUIA_String_Accept, "0123456789",
MUIA_String_Integer, 0,
End,
End,
Child, HGroup,
MUIA_Group_SameSize, TRUE,
Child, BT_EUse = KeyButton("Ok" , 'o'),
Child, HSpace(0),
Child, BT_ECancel = KeyButton("Cancel", 'c'),
End,
End,
End,
End;
if (!App)
Sense(App, "Failed to create application.");
DoMethod(WI_Manager, MUIM_Notify, MUIA_Window_CloseRequest, TRUE, App, 2, MUIM_Application_ReturnID, MID_OK);
/*
DoMethod(ST_Path , MUIM_Notify, MUIA_String_Acknowledge, MUIV_EveryTime, App, 2, MUIM_Application_ReturnID, MID_PATH);
*/
DoMethod(LV_Areas , MUIM_Notify, MUIA_Listview_DoubleClick, TRUE, App, 2, MUIM_Application_ReturnID, MID_DOUBLE);
DoMethod(LV_Areas , MUIM_Notify, MUIA_List_Active, MUIV_EveryTime, App, 2, MUIM_Application_ReturnID, MID_SELAREA);
DoMethod(BT_Up , MUIM_Notify, MUIA_Pressed, FALSE, App, 2, MUIM_Application_ReturnID, MID_UP);
DoMethod(BT_Down , MUIM_Notify, MUIA_Pressed, FALSE, App, 2, MUIM_Application_ReturnID, MID_DOWN);
DoMethod(BT_Parent , MUIM_Notify, MUIA_Pressed, FALSE, App, 2, MUIM_Application_ReturnID, MID_PARENT);
DoMethod(BT_Child , MUIM_Notify, MUIA_Pressed, FALSE, App, 2, MUIM_Application_ReturnID, MID_CHILD);
DoMethod(BT_Cut , MUIM_Notify, MUIA_Pressed, FALSE, App, 2, MUIM_Application_ReturnID, MID_CUT);
DoMethod(BT_Copy , MUIM_Notify, MUIA_Pressed, FALSE, App, 2, MUIM_Application_ReturnID, MID_COPY);
DoMethod(BT_Paste , MUIM_Notify, MUIA_Pressed, FALSE, App, 2, MUIM_Application_ReturnID, MID_PASTE);
DoMethod(BT_Add , MUIM_Notify, MUIA_Pressed, FALSE, App, 2, MUIM_Application_ReturnID, MID_ADD);
DoMethod(BT_Remove , MUIM_Notify, MUIA_Pressed, FALSE, App, 2, MUIM_Application_ReturnID, MID_REMOVE);
DoMethod(BT_Sort , MUIM_Notify, MUIA_Pressed, FALSE, App, 2, MUIM_Application_ReturnID, MID_SORT);
DoMethod(BT_Edit , MUIM_Notify, MUIA_Pressed, FALSE, App, 2, MUIM_Application_ReturnID, MID_EDIT);
DoMethod(WI_Manager, MUIM_Window_SetCycleChain, /* ST_Path, */ LV_Areas,
BT_Parent, BT_Child, BT_Cut, BT_Copy, BT_Paste, BT_Add, BT_Remove,
BT_Up, BT_Down, BT_Sort, BT_Edit, NULL);
set(WI_Manager, MUIA_Window_DefaultObject, LV_Areas);
DoMethod(WI_Editor , MUIM_Notify, MUIA_Window_CloseRequest, TRUE, App, 2, MUIM_Application_ReturnID, EID_CANCEL);
DoMethod(BT_EUse , MUIM_Notify, MUIA_Pressed, FALSE, App, 2, MUIM_Application_ReturnID, EID_USE);
DoMethod(BT_ECancel, MUIM_Notify, MUIA_Pressed, FALSE, App, 2, MUIM_Application_ReturnID, EID_CANCEL);
DoMethod(LV_AccBits, MUIM_Notify, MUIA_List_Active, MUIV_EveryTime, App, 2, MUIM_Application_ReturnID, EID_SELAB);
DoMethod(ST_AccBit , MUIM_Notify, MUIA_String_Acknowledge, MUIV_EveryTime, App, 2, MUIM_Application_ReturnID, EID_NAMEAB);
DoMethod(CY_ATypePublic, MUIM_Notify, MUIA_Cycle_Active, MUIV_EveryTime, App, 2, MUIM_Application_ReturnID, EID_CGTYPE);
DoMethod(WI_Editor, MUIM_Window_SetCycleChain,
ST_Name, ST_Info, ST_MBName, ST_FilePath, ST_HoldNum, ST_HoldDays,
CH_Group, CH_ToName, CH_NoRe, CH_Pseudos, SL_RLevel, SL_WLevel,
SL_ELevel, CY_ATypeRoot, CY_ATypePublic, LV_AccBits, ST_AccBit,
ST_QuoteStr, ST_PQuoteStr, ST_ResendStr, ST_ForwardStr,
ST_OriginStr, BT_EUse, BT_ECancel, NULL);
set(WI_Editor, MUIA_Window_DefaultObject, LV_AccBits);
STRPTR entry;
UBYTE n;
for(n = 0; n < 32; n++)
{
entry = AccBitNames[n];
DoMethod(LV_AccBits, MUIM_List_Insert, &entry, 1, MUIV_List_Insert_Bottom);
}
if (Areaname)
{
TakeASem(FALSE);
CurrentMother = NULL;
CurrentArea = ResolvePath(Areaname);
UpdatePath();
DropASem();
if (!CurrentArea)
{
if (!CurrentMother)
{
MUI_RequestA(App, NULL, 0, "KMSAM Error", "I see", "Invalid path specification.", NULL);
Sense(App, NULL);
}
else if (!MUI_RequestA(App, NULL, 0, "KMSAM Error", "Create|Abort", "Area does not exist.", NULL))
Sense(App, NULL);
}
TakeASem(FALSE);
index = DisplayDir(CurrentMother, CurrentArea);
DropASem();
set(LV_Areas, MUIA_List_Active, index);
if (CurrentArea)
DoMethod(App, MUIM_Application_ReturnID, MID_EDIT);
else
DoMethod(App, MUIM_Application_ReturnID, MID_ADD);
}
else
{
TakeASem(FALSE);
CurrentMother = NULL;
CurrentArea = SetArea(1);
UpdatePath();
index = DisplayDir(CurrentMother, CurrentArea);
DropASem();
set(LV_Areas, MUIA_List_Active, index);
ULONG open;
set(WI_Manager, MUIA_Window_Open, TRUE);
get(WI_Manager, MUIA_Window_Open, &open);
if (!open)
Sense(App, "Failed to open window.");
DoMethod(WI_Manager, MUIM_Window_ScreenToFront,);
}
while(running)
{
switch(DoMethod(App, MUIM_Application_Input, &signal))
{
case MID_ABOUT:
MUI_RequestA(App, NULL, 0, "Information", "Ok",
eC ePW "KMS Area Manager\n\n"
ePB "Version " VERSION " (" __COMMODORE_DATE__ ")\n"
"Copyright 1994 by Thomas Schwarz.\n"
"\nThis is a MUI-Application.\n"
"MUI is copyrighted by Stefan Stuntz.", NULL);
break;
case MID_COPY:
if (!CurrentMother)
{
DisplayBeep(0);
MUI_RequestA(App, NULL, 0, "KMSAM Error", "I see", "Function inoperable in root area!", NULL);
break;
}
DoMethod(LV_Areas, MUIM_List_GetEntry, MUIV_List_GetEntry_Active, &an);
if (an)
{
if (an->AreaData.Daughter)
{
MUI_RequestA(App, NULL, 0, "KMSAM Error", "I see", "Not possible for parent areas.", NULL);
break;
}
AreaStore = an->AreaData;
}
else
MUI_RequestA(App, NULL, 0, "KMSAM Error", "I see", "Copy failed!", NULL);
break;
case MID_UP:
get(LV_Areas, MUIA_List_Entries, &entries);
get(LV_Areas, MUIA_List_Active, &num);
if (num != MUIV_List_Active_Off && num > 0)
{
if (num > 1)
DoMethod(LV_Areas, MUIM_List_GetEntry, num-2, &an);
else
an = NULL;
DoMethod(LV_Areas, MUIM_List_GetEntry, num-1, &an2);
DoMethod(LV_Areas, MUIM_List_GetEntry, num, &an3);
TakeASem(TRUE);
if (an)
an->AreaData.Next = an3->AreaData.ID;
else
CurrentMother->AreaData.Daughter = an3->AreaData.ID;
idmerk = an3->AreaData.Next;
an3->AreaData.Next = an2->AreaData.ID;
an2->AreaData.Next = idmerk;
DropASem();
DoMethod(LV_Areas, MUIM_List_Exchange, num, num-1);
set(LV_Areas, MUIA_List_Active, MUIV_List_Active_Up);
areaschanged = TRUE;
}
else
DisplayBeep(0);
break;
case MID_DOWN:
get(LV_Areas, MUIA_List_Entries, &entries);
get(LV_Areas, MUIA_List_Active, &num);
if (num != MUIV_List_Active_Off && num < entries-1)
{
if (num > 0)
DoMethod(LV_Areas, MUIM_List_GetEntry, num-1, &an);
else
an = NULL;
DoMethod(LV_Areas, MUIM_List_GetEntry, num, &an2);
DoMethod(LV_Areas, MUIM_List_GetEntry, num+1, &an3);
TakeASem(TRUE);
if (an)
an->AreaData.Next = an3->AreaData.ID;
else
CurrentMother->AreaData.Daughter = an3->AreaData.ID;
idmerk = an3->AreaData.Next;
an3->AreaData.Next = an2->AreaData.ID;
an2->AreaData.Next = idmerk;
DropASem();
DoMethod(LV_Areas, MUIM_List_Exchange, num, num+1);
set(LV_Areas, MUIA_List_Active, MUIV_List_Active_Down);
areaschanged = TRUE;
}
else
DisplayBeep(0);
break;
case MID_PASTE:
if (!CurrentMother)
{
DisplayBeep(0);
MUI_RequestA(App, NULL, 0, "KMSAM Error", "I see", "Function inoperable in root area!", NULL);
break;
}
if (!AreaStore.ID)
{
DisplayBeep(0);
MUI_RequestA(App, NULL, 0, "KMSAM Error", "I see", "Paste buffer is empty!", NULL);
break;
}
TakeASem(TRUE);
an = AddAN();
if (an)
{
/* Areadaten übernehmen */
idmerk = an->AreaData.ID;
an->AreaData = AreaStore;
an->AreaData.ID = idmerk;
an->AreaData.Next = 0;
an->AreaData.Mother = 0;
if (an2 = SetArea(an->AreaData.Daughter))
{
an2->AreaData.Mother = idmerk;
while(an2 = SetArea(an2->AreaData.Next))
an2->AreaData.Mother = idmerk;
}
/* Area in Liste aufnehmen */
LONG index = InsertArea(an);
DoMethod(LV_Areas, MUIM_List_Insert, &an, 1, index);
set(LV_Areas, MUIA_List_Active, index);
areaschanged = TRUE;
}
else
DisplayBeep(0);
DropASem();
break;
case MID_ADD:
if (!CurrentMother)
{
DisplayBeep(0);
MUI_RequestA(App, NULL, 0, "KMSAM Error", "I see", "Function inoperable in root area!", NULL);
break;
}
TakeASem(TRUE);
an = AddAN();
if (an)
{
addflag = TRUE;
if (Areaname)
{
STRPTR sp = Areaname + strlen(Areaname);
while(sp != Areaname && *sp != '/')
sp--;
if (*sp == '/')
sp++;
Upper(sp);
strcpy(an->AreaData.Name, sp);
}
else
*an->AreaData.Name = '\0';
an->AreaData.Type = ATYPE_NEWS;
an->AreaData.EditLevel = 255;
an->AreaData.QuoteStr = 1;
an->AreaData.PQuoteStr = 1;
an->AreaData.ResendStr = 1;
an->AreaData.ForwardStr = 1;
an->AreaData.OriginStr = 1;
DoMethod(App, MUIM_Application_ReturnID, MID_EDIT);
}
else if (Areaname)
{
DisplayBeep(0);
DoMethod(App, MUIM_Application_ReturnID, MID_OK);
}
else
DisplayBeep(0);
DropASem();
break;
case MID_CUT:
if (!CurrentMother)
{
DisplayBeep(0);
MUI_RequestA(App, NULL, 0, "KMSAM Error", "I see", "Can't cut root area!", NULL);
break;
}
cut = TRUE;
case MID_REMOVE:
if (!CurrentMother)
{
DisplayBeep(0);
MUI_RequestA(App, NULL, 0, "KMSAM Error", "I see", "Can't remove root area!", NULL);
break;
}
DoMethod(LV_Areas, MUIM_List_GetEntry, MUIV_List_GetEntry_Active, &an);
if (an)
{
/* Wenn Area momentan CurrentArea eines Users, nicht löschen */
TakeMSem(FALSE);
struct KMSNode *member = KMSBase->MemberList.mlh_Head;
error = FALSE;
while(!error && member->Node.mln_Succ)
{
if (member->LCPtr->Session.CurrentArea == an)
{
MUI_RequestA(App, NULL, 0, "KMSAM Error", "I see", "Area currently in use!", NULL);
error = TRUE;
}
member = member->Node.mln_Succ;
}
DropMSem();
/* Wirklich löschen? */
if (!error && !cut)
if (!MUI_RequestA(App, NULL, 0, "KMSAM Request", "Just do it!|Oh no!", "Really delete area?", NULL))
error = TRUE;
if (!error)
{
if (cut)
AreaStore = an->AreaData;
TakeASem(TRUE);
RemoveArea(an);
DeleteAN(an);
DoMethod(LV_Areas, MUIM_List_Remove, MUIV_List_Remove_Active);
DoMethod(LV_Areas, MUIM_List_GetEntry, MUIV_List_GetEntry_Active, &CurrentArea);
UpdatePath();
DropASem();
areaschanged = TRUE;
}
}
else
DisplayBeep(0);
cut = FALSE;
break;
case MID_SORT:
struct AreaNode *next, *last;
LONG n = 0;
if (!CurrentArea)
MUI_RequestA(App, NULL, 0, "KMSAM Error", "I see", "There's nothing there to be sorted!", NULL);
else
{
TakeASem(TRUE);
DoMethod(LV_Areas, MUIM_List_Sort,);
DoMethod(LV_Areas, MUIM_List_GetEntry, n++, &next);
last = next;
if (next)
CurrentMother->AreaData.Daughter = next->AreaData.ID;
while(next)
{
last = next;
DoMethod(LV_Areas, MUIM_List_GetEntry, n++, &next);
if (next)
last->AreaData.Next = next->AreaData.ID;
}
if (last)
last->AreaData.Next = 0;
set(LV_Areas, MUIA_List_Active, 0);
areaschanged = TRUE;
DropASem();
}
break;
case MID_EDIT:
if (!addflag)
DoMethod(LV_Areas, MUIM_List_GetEntry, MUIV_List_GetEntry_Active, &an);
if (an)
{
area = an->AreaData;
set(ST_Name, MUIA_String_Contents, area.Name);
set(ST_Info, MUIA_String_Contents, area.Info);
set(ST_MBName, MUIA_String_Contents, area.MBName);
set(ST_FilePath, MUIA_String_Contents, area.FilePath);
set(ST_QuoteStr, MUIA_String_Integer, area.QuoteStr);
set(ST_PQuoteStr, MUIA_String_Integer, area.PQuoteStr);
set(ST_ResendStr, MUIA_String_Integer, area.ResendStr);
set(ST_ForwardStr, MUIA_String_Integer, area.ForwardStr);
set(ST_OriginStr, MUIA_String_Integer, area.OriginStr);
set(SL_RLevel, MUIA_Slider_Level, area.ReadLevel);
set(SL_WLevel, MUIA_Slider_Level, area.WriteLevel);
set(SL_ELevel, MUIA_Slider_Level, area.EditLevel);
set(ST_HoldNum, MUIA_String_Integer, area.HoldNum);
set(ST_HoldDays, MUIA_String_Integer, area.HoldDays);
for(num = 0; num < 32; num++)
DoMethod(LV_AccBits, MUIM_List_Select, num, MUIV_List_Select_Off, NULL);
num = 0;
acc = area.AccessBits;
while(acc)
{
if (acc & 1)
DoMethod(LV_AccBits, MUIM_List_Select, num, MUIV_List_Select_On, NULL);
acc = acc / 2;
num++;
}
set(CH_Group, MUIA_Selected, (area.Type & ATYPE_GROUP) ? TRUE : FALSE);
set(CH_NoRe, MUIA_Selected, (area.WriteFlag & AWF_NORE) ? FALSE : TRUE);
set(CH_Pseudos, MUIA_Selected, (area.WriteFlag & AWF_PSEUDO) ? TRUE : FALSE);
set(CH_ToName, MUIA_Selected, (area.WriteFlag & AWF_TONAME) ? TRUE : FALSE);
if (area.ID == 1)
{
set(ST_MBName, MUIA_Disabled, TRUE);
set(CH_Group, MUIA_Disabled, TRUE);
set(CH_ToName, MUIA_Selected, TRUE);
set(CH_ToName, MUIA_Disabled, TRUE);
set(ST_FilePath, MUIA_Disabled, FALSE);
set(PG_AType, MUIA_Group_ActivePage, 0);
}
else
{
set(ST_MBName, MUIA_Disabled, FALSE);
set(CH_Group, MUIA_Disabled, FALSE);
set(CH_ToName, MUIA_Disabled, FALSE);
set(PG_AType, MUIA_Group_ActivePage, 1);
num = 0;
if (area.Type & ATYPE_FILES)
{
set(ST_FilePath, MUIA_Disabled, FALSE);
num = 1;
}
else
set(ST_FilePath, MUIA_Disabled, TRUE);
set(CY_ATypePublic, MUIA_Cycle_Active, num);
}
ULONG edopen;
set(WI_Editor, MUIA_Window_Open, TRUE);
get(WI_Editor, MUIA_Window_Open, &edopen);
if (!edopen)
{
MUI_RequestA(App, NULL, 0, "KMSAM Error", "I see", "Couldn't open window!", NULL);
if (addflag)
{
TakeASem(TRUE);
DeleteAN(an);
DropASem();
}
addflag = FALSE;
if (Areaname)
DoMethod(App, MUIM_Application_ReturnID, MID_OK);
}
else
set(WI_Manager, MUIA_Window_Sleep, TRUE);
DoMethod(WI_Editor, MUIM_Window_ScreenToFront,);
}
else
{
DisplayBeep(0);
if (Areaname)
DoMethod(App, MUIM_Application_ReturnID, MID_OK);
}
break;
case MID_OK:
case MUIV_Application_ReturnID_Quit:
if (addflag)
{
TakeASem(TRUE);
DeleteAN(an);
DropASem();
}
addflag = FALSE;
CleanUpAreaList();
if (!Areaname || !FindPort("KMS"))
{
set(App, MUIA_Application_Sleep, TRUE);
if (areaschanged)
{
if (!WriteAreaList())
MUI_RequestA(App, NULL, 0, "KMSAM Error", "I see", "Saving arealist failed!", NULL);
}
if (bitschanged)
{
if (!WriteAccBits())
MUI_RequestA(App, NULL, 0, "KMSAM Error", "I see", "Saving access bits failed!", NULL);
}
set(App, MUIA_Application_Sleep, FALSE);
}
else if (areaschanged)
KMSBase->Modified |= MODIFIED_AREAS;
running = FALSE;
break;
case MID_CHILD:
case MID_DOUBLE:
DoMethod(LV_Areas, MUIM_List_GetEntry, MUIV_List_GetEntry_Active, &an);
if (an)
{
TakeASem(FALSE);
if (an->AreaData.Daughter)
{
CurrentMother = an;
CurrentArea = SetArea(an->AreaData.Daughter);
index = DisplayDir(CurrentMother, CurrentArea);
set(LV_Areas, MUIA_List_Active, index);
}
else
{
CurrentMother = an;
CurrentArea = NULL;
DisplayDir(CurrentMother, CurrentArea);
}
UpdatePath();
DropASem();
}
else
DisplayBeep(0);
break;
case MID_PARENT:
if (CurrentMother)
{
TakeASem(FALSE);
CurrentArea = CurrentMother;
CurrentMother = SetArea(CurrentMother->AreaData.Mother);
index = DisplayDir(CurrentMother, CurrentArea);
set(LV_Areas, MUIA_List_Active, index);
DropASem();
}
else
DisplayBeep(0);
break;
case MID_SELAREA:
set(WI_Manager, MUIA_Window_ActiveObject, LV_Areas);
DoMethod(LV_Areas, MUIM_List_GetEntry, MUIV_List_GetEntry_Active, &CurrentArea);
TakeASem(FALSE);
UpdatePath();
DropASem();
break;
case EID_SELAB:
set(WI_Editor, MUIA_Window_ActiveObject, LV_AccBits);
get(LV_AccBits, MUIA_List_Active, &num);
set(ST_AccBit, MUIA_String_Contents, AccBitNames[num]);
break;
case EID_NAMEAB:
STRPTR text;
get(LV_AccBits, MUIA_List_Active, &num);
get(ST_AccBit, MUIA_String_Contents, &text);
strcpy(AccBitNames[num], text);
DoMethod(LV_AccBits, MUIM_List_Redraw, MUIV_List_Redraw_Active);
bitschanged = TRUE;
break;
case EID_CGTYPE:
get(CY_ATypePublic, MUIA_Cycle_Active, &num);
if (num == 0) /* News */
{
set(ST_FilePath, MUIA_String_Contents, "");
set(ST_FilePath, MUIA_Disabled, TRUE);
}
else if (num == 1) /* Binary */
set(ST_FilePath, MUIA_Disabled, FALSE);
break;
case EID_USE:
STRPTR text;
ULONG value;
get(ST_Name, MUIA_String_Contents, &text);
strcpy(area.Name, text);
Upper(area.Name);
get(ST_Info, MUIA_String_Contents, &text);
strcpy(area.Info, text);
get(ST_MBName, MUIA_String_Contents, &text);
strcpy(area.MBName, text);
get(ST_FilePath, MUIA_String_Contents, &text);
strcpy(area.FilePath, text);
get(ST_QuoteStr, MUIA_String_Integer, &value);
area.QuoteStr = value;
get(ST_PQuoteStr, MUIA_String_Integer, &value);
area.PQuoteStr = value;
get(ST_ResendStr, MUIA_String_Integer, &value);
area.ResendStr = value;
get(ST_ForwardStr, MUIA_String_Integer, &value);
area.ForwardStr = value;
get(ST_OriginStr, MUIA_String_Integer, &value);
area.OriginStr = value;
get(SL_RLevel, MUIA_Slider_Level, &value);
area.ReadLevel = (UWORD)value;
get(SL_WLevel, MUIA_Slider_Level, &value);
area.WriteLevel = (UWORD)value;
get(SL_ELevel, MUIA_Slider_Level, &value);
area.EditLevel = (UWORD)value;
get(ST_HoldNum, MUIA_String_Integer, &value);
area.HoldNum = value;
get(ST_HoldDays, MUIA_String_Integer, &value);
area.HoldDays = value;
acc = 1;
area.AccessBits = 0;
for(num = 0; num < 32; num++)
{
DoMethod(LV_AccBits, MUIM_List_Select, num, MUIV_List_Select_Ask, &state);
if (state == MUIV_List_Select_On)
area.AccessBits |= acc;
acc = acc << 1;
}
if (area.ID == 1)
area.Type = ATYPE_PRIVATE;
else
{
get(CY_ATypePublic, MUIA_Cycle_Active, &num);
if (num == 0)
area.Type = ATYPE_NEWS;
else if (num == 1)
area.Type = ATYPE_FILES;
}
get(CH_Group, MUIA_Selected, &num);
if (num)
area.Type |= ATYPE_GROUP;
area.WriteFlag = 0;
get(CH_ToName, MUIA_Selected, &num);
if (num)
area.WriteFlag |= AWF_TONAME;
get(CH_NoRe, MUIA_Selected, &num);
if (!num)
area.WriteFlag |= AWF_NORE;
get(CH_Pseudos, MUIA_Selected, &num);
if (num)
area.WriteFlag |= AWF_PSEUDO;
Forbid();
an->AreaData = area;
Permit();
if (addflag)
{
/* Area in Liste aufnehmen */
TakeASem(TRUE);
LONG index = InsertArea(an);
DropASem();
DoMethod(LV_Areas, MUIM_List_Insert, &an, 1, index);
set(LV_Areas, MUIA_List_Active, index);
addflag = FALSE;
}
else
DoMethod(LV_Areas, MUIM_List_Redraw, MUIV_List_Redraw_Active);
areaschanged = TRUE;
// no break!
case EID_CANCEL:
if (addflag)
{
TakeASem(TRUE);
DeleteAN(an);
DropASem();
}
addflag = FALSE;
set(WI_Editor, MUIA_Window_Open, FALSE);
set(WI_Manager, MUIA_Window_Sleep, FALSE);
TakeASem(FALSE);
UpdatePath();
DropASem();
if (Areaname)
DoMethod(App, MUIM_Application_ReturnID, MID_OK);
break;
}
if (running && signal)
Wait(signal);
}
Sense(App, NULL);
}
///
/************************************
* DisplayDir: Directory anzeigen *
************************************
* I: CurrentMother, CurrentArea *
* O: Index CurrentArea in Listview *
************************************/
/// "DisplayDir"
LONG DisplayDir(struct AreaNode *mother, struct AreaNode *anode)
{
struct AreaNode *current;
LONG result = MUIV_List_Active_Off;
LONG count = 0;
DoMethod(LV_Areas, MUIM_List_Clear,);
/* Auf erste Tochter positionieren */
if (mother)
current = SetArea(mother->AreaData.Daughter);
else
current = (struct AreaNode *)KMSBase->AreaList.mlh_Head;
if (!current || !current->Node.mln_Succ)
return result;
set(LV_Areas, MUIA_List_Quiet, TRUE);
do
{
DoMethod(LV_Areas, MUIM_List_Insert, ¤t, 1, MUIV_List_Insert_Bottom);
if (current && current == anode)
result = count;
current = SetArea(current->AreaData.Next);
count++;
} while(current);
set(LV_Areas, MUIA_List_Quiet, FALSE);
return result;
}
///
/*********************************
* AreaList einlesen *
*********************************
* I: --- *
* O: Erfolg? TRUE/FALSE *
*********************************/
/// "ReadAreaList"
BOOL ReadAreaList(VOID)
{
struct AreaNode *apoint;
struct Area area;
TEXT buffer[LEN_DOSPATH+1];
TEXT buff[LEN_MBNAME+2]; /* MBNAME ist laengstes Element */
FILE *file;
/* Wenn schon eingelesen, fertig */
apoint = (struct AreaNode *)KMSBase->AreaList.mlh_Head;
if (apoint->Node.mln_Succ)
return TRUE;
/* Einlesen */
ObtainSemaphore(&KMSBase->AreaSem);
strcpy(buffer, KMSBase->DatDir);
strcat(buffer, "KMS_AREAS.DAT");
if (!(file = fopen(buffer, "r")))
{
ReleaseSemaphore(&KMSBase->AreaSem);
return FALSE;
}
else
{
while(fgets(buff, LEN_AREANAME+2, file))
{
if (strlen(buff))
buff[strlen(buff)-1] = '\0'; /* Linefeed am Ende entfernen */
if (!(apoint = (struct AreaNode *)AllocMem((ULONG)sizeof(struct AreaNode),MEMF_PUBLIC|MEMF_CLEAR)))
{
Error("out of memory.");
fclose(file);
ReleaseSemaphore(&KMSBase->AreaSem);
return FALSE;
}
clrmem(&area, sizeof(struct Area));
strcpy(area.Name, buff);
if (fgets(buff, LEN_AREAINFO+2, file))
{
if (strlen(buff))
buff[strlen(buff)-1] = '\0'; /* Linefeed am Ende entfernen */
strcpy(area.Info, buff);
}
if (fgets(buff, LEN_MBNAME+2, file))
{
if (strlen(buff))
buff[strlen(buff)-1] = '\0';
strcpy(area.MBName, buff);
}
if (fgets(buff, LEN_FILEAREA+2, file))
{
if (strlen(buff))
buff[strlen(buff)-1] = '\0';
strcpy(area.FilePath, buff);
}
if (fgets(buff, LEN_NUMBER+2, file))
area.ID = (UWORD)atoi(buff);
if (fgets(buff, LEN_NUMBER+2, file))
area.Type = (UBYTE)atoi(buff);
if (fgets(buff, LEN_NUMBER+2, file))
area.ReadLevel = (UBYTE)atoi(buff);
if (fgets(buff, LEN_NUMBER+2, file))
area.WriteLevel = (UBYTE)atoi(buff);
if (fgets(buff, LEN_NUMBER+2, file))
area.EditLevel = (UBYTE)atoi(buff);
if (fgets(buff, LEN_NUMBER+2, file))
area.AccessBits = (ULONG)atol(buff);
if (fgets(buff, LEN_NUMBER+2, file))
area.WriteFlag = (UWORD)atol(buff);
if (fgets(buff, LEN_NUMBER+2, file))
area.QuoteStr = (UBYTE)atoi(buff);
if (fgets(buff, LEN_NUMBER+2, file))
area.PQuoteStr = (UBYTE)atoi(buff);
if (fgets(buff, LEN_NUMBER+2, file))
area.ResendStr = (UBYTE)atoi(buff);
if (fgets(buff, LEN_NUMBER+2, file))
area.ForwardStr = (UBYTE)atoi(buff);
if (fgets(buff, LEN_NUMBER+2, file))
area.OriginStr = (UBYTE)atoi(buff);
if (fgets(buff, LEN_NUMBER+2, file))
area.HoldNum = (UWORD)atoi(buff);
if (fgets(buff, LEN_NUMBER+2, file))
area.HoldDays = (UWORD)atoi(buff);
if (fgets(buff, LEN_NUMBER+2, file))
area.Mother = (UWORD)atoi(buff);
if (fgets(buff, LEN_NUMBER+2, file))
area.Daughter = (UWORD)atoi(buff);
if (fgets(buff, LEN_NUMBER+2, file))
area.Next = (UWORD)atoi(buff);
apoint->AreaData = area;
AddTail((struct List *)&KMSBase->AreaList, (struct Node *)apoint);
}
fclose(file);
}
ReleaseSemaphore(&KMSBase->AreaSem);
return TRUE;
}
///
/*********************************
* AreaList schreiben *
*********************************
* I: --- *
* O: Erfolg? TRUE/FALSE *
*********************************/
/// "WriteAreaList"
BOOL WriteAreaList(VOID)
{
struct AreaNode *apoint;
TEXT buffer[LEN_DOSPATH+1];
FILE *file;
/* Daten werden nur im Besitz der Semaphore geschrieben */
strcpy(buffer, KMSBase->DatDir);
strcat(buffer, "KMS_AREAS.DAT");
file = fopen(buffer, "w");
if (!file)
return FALSE;
TakeASem(TRUE);
apoint = (struct AreaNode *)KMSBase->AreaList.mlh_Head;
while(apoint->Node.mln_Succ)
{
fprintf(file,"%s\n%s\n%s\n%s\n", apoint->AreaData.Name,
apoint->AreaData.Info,
apoint->AreaData.MBName,
apoint->AreaData.FilePath);
fprintf(file,"%d\n%d\n%d\n%d\n%d\n", apoint->AreaData.ID,
apoint->AreaData.Type,
apoint->AreaData.ReadLevel,
apoint->AreaData.WriteLevel,
apoint->AreaData.EditLevel);
fprintf(file,"%ld\n%d\n", apoint->AreaData.AccessBits,
apoint->AreaData.WriteFlag);
fprintf(file,"%d\n%d\n%d\n%d\n%d\n", apoint->AreaData.QuoteStr,
apoint->AreaData.PQuoteStr,
apoint->AreaData.ResendStr,
apoint->AreaData.ForwardStr,
apoint->AreaData.OriginStr);
fprintf(file,"%d\n", apoint->AreaData.HoldNum);
fprintf(file,"%d\n", apoint->AreaData.HoldDays);
fprintf(file,"%d\n%d\n%d\n", apoint->AreaData.Mother,
apoint->AreaData.Daughter,
apoint->AreaData.Next);
apoint = apoint->Node.mln_Succ;
}
fclose(file);
DropASem();
return TRUE;
}
///
/*********************************
* Areadatei initialisieren *
*********************************
* I: --- *
* O: Erfolg TRUE/FALSE *
*********************************/
/// "InitAreaFile"
BOOL InitAreaFile(VOID)
{
TEXT buffer[LEN_DOSPATH+1];
struct Area area;
FILE *file;
TakeASem(TRUE);
strcpy(buffer, KMSBase->DatDir);
strcat(buffer, "KMS_AREAS.DAT");
if (!(file = fopen(buffer, "w")))
{
DropASem();
return FALSE;
}
clrmem(&area, sizeof(struct Area));
strcpy(area.Name, "PRIVAT");
strcpy(area.Info, "- Private Mail -");
strcpy(area.MBName, "");
strcpy(area.FilePath, "KMS:Files/");
area.ID = 1;
area.Type = ATYPE_PRIVATE;
area.ReadLevel = 1;
area.WriteLevel = 1;
area.EditLevel = 255;
area.QuoteStr = 1;
area.PQuoteStr = 1;
area.ResendStr = 1;
area.ForwardStr = 1;
area.OriginStr = 1;
area.HoldNum = 0;
area.HoldDays = 0;
fprintf(file, "%s\n%s\n%s\n%s\n", area.Name,
area.Info,
area.MBName,
area.FilePath);
fprintf(file, "%d\n%d\n%d\n%d\n%d\n", area.ID,
area.Type,
area.ReadLevel,
area.WriteLevel,
area.EditLevel);
fprintf(file, "%ld\n%d\n", area.AccessBits,
area.WriteFlag);
fprintf(file, "%d\n%d\n%d\n%d\n%d\n", area.QuoteStr,
area.PQuoteStr,
area.ResendStr,
area.ForwardStr,
area.OriginStr);
fprintf(file, "%d\n", area.HoldNum);
fprintf(file, "%d\n", area.HoldDays);
fprintf(file, "%d\n%d\n%d\n", area.Mother,
area.Daughter,
area.Next);
fclose(file);
DropASem();
return TRUE;
}
///
/********************************
* Neuen AreaNode einrichten *
********************************
* I: --- *
* O: struct AreaNode * *
********************************/
/// "AddAN"
struct AreaNode *AddAN(VOID)
{
struct AreaNode *apoint, *newapoint;
UWORD id = 0, previd = 0;
/* Größte ID suchen */
apoint = (struct AreaNode *)KMSBase->AreaList.mlh_Head;
while(apoint->Node.mln_Succ)
{
if (apoint->AreaData.ID > previd)
previd = apoint->AreaData.ID;
apoint = apoint->Node.mln_Succ;
}
if (previd + 1 == 0) /* ID-Überlauf */
{
previd = 0; id = 0;
apoint = (struct AreaNode *)KMSBase->AreaList.mlh_Head;
if (apoint->Node.mln_Succ)
id = apoint->AreaData.ID;
while(apoint->Node.mln_Succ && previd + 1 == id)
{
previd = id;
apoint = (struct AreaNode *)apoint->Node.mln_Succ;
if (apoint->Node.mln_Succ)
id = apoint->AreaData.ID;
}
}
if (previd > 0 && previd == id)
{
MUI_RequestA(App, NULL, 0, "KMSAM Error", "I see", "Too many areas!", NULL);
return NULL;
}
if (!(newapoint = (struct AreaNode *)AllocMem((ULONG)sizeof(struct AreaNode), MEMF_PUBLIC|MEMF_CLEAR)))
{
MUI_RequestA(App, NULL, 0, "KMSAM Error", "I see", "Out of memory!", NULL);
return NULL;
}
newapoint->AreaData.ID = previd + 1;
Insert((struct List *)&KMSBase->AreaList, (struct Node *)newapoint, (struct Node *)apoint->Node.mln_Pred);
return newapoint;
}
///
/********************************
* AreaNode löschen *
********************************
* I: struct AreaNode * *
* O: --- *
********************************/
/// "DeleteAN"
VOID DeleteAN(struct AreaNode *an)
{
if (!an)
return;
Remove((struct Node *)an);
FreeMem(an, (ULONG)sizeof(struct AreaNode));
}
///
/****************************
* Parse Arguments *
****************************
* I: --- *
* O: Error: FALSE Ok: TRUE *
****************************/
/// "ParseArgs"
#define TEMPLATE "AREANAME"
STRPTR HelpTxt = "\nUsage:\n\nAREANAME optional: Area to edit (May be complete KMS path)\n\n";
BOOL ParseArgs(VOID)
{
UBYTE n;
ULONG args[1];
struct RDArgs *rargs = NULL;
struct RDArgs *myrdargs = NULL;
for(n = 0; n < 1; n++)
args[n] = 0;
myrdargs = AllocDosObjectTags(DOS_RDARGS, TAG_DONE);
if (!myrdargs)
{
PrintFault(IoErr(), NULL);
return FALSE;
}
myrdargs->RDA_ExtHelp = HelpTxt;
if (!(rargs = (struct RDArgs *)ReadArgs(TEMPLATE, args, myrdargs)))
{
PrintFault(IoErr(), NULL);
FreeDosObject(DOS_RDARGS, myrdargs);
return FALSE;
}
if (args[0]) /* AREANAME */
Areaname = (STRPTR)strdup((STRPTR)args[0]);
FreeArgs(rargs);
FreeDosObject(DOS_RDARGS, myrdargs);
return TRUE;
}
///
/****************************
* Sense *
****************************
* I: --- *
* O: --- *
****************************/
/// "Sense"
VOID Sense(APTR app, STRPTR str)
{
if (app)
MUI_DisposeObject(app);
if (Areaname)
free(Areaname);
if (KMSBase)
{
/* Von der Basis abmelden */
ReleaseSemaphore(&KMSBase->BaseSem);
/* KMSBase gegebenenfalls wieder entfernen */
Forbid();
if (KMSBase = (struct KMSBase *)FindSemaphore(KMSBASENAME))
{
if (AttemptSemaphore(&KMSBase->BaseSem))
{
Permit();
/* Arealiste freigeben */
struct AreaNode *apoint = KMSBase->AreaList.mlh_Head;
while(apoint->Node.mln_Succ)
{
struct AreaNode *nextapoint = apoint->Node.mln_Succ;
Remove((struct Node *)apoint);
FreeMem(apoint, (ULONG)sizeof(struct AreaNode));
apoint = nextapoint;
}
/* Userliste freigeben */
struct UserNode *upoint = KMSBase->UserList.mlh_Head;
while(upoint->Node.mln_Succ)
{
struct UserNode *nextupoint = upoint->Node.mln_Succ;
Remove((struct Node *)upoint);
FreeMem(upoint, (ULONG)sizeof(struct UserNode));
upoint = nextupoint;
}
if (KMSBase->DatDir)
FreeMem(KMSBase->DatDir, strlen(KMSBase->DatDir) + 1);
if (KMSBase->UserDir)
FreeMem(KMSBase->UserDir, strlen(KMSBase->UserDir) + 1);
RemSemaphore(&KMSBase->BaseSem);
ObtainSemaphore(&KMSBase->UserSem);
ReleaseSemaphore(&KMSBase->UserSem);
ObtainSemaphore(&KMSBase->AreaSem);
ReleaseSemaphore(&KMSBase->AreaSem);
ObtainSemaphore(&KMSBase->SaveSem);
ReleaseSemaphore(&KMSBase->SaveSem);
ReleaseSemaphore(&KMSBase->BaseSem);
FreeMem(KMSBase->BaseSem.ss_Link.ln_Name, sizeof(KMSBASENAME)+1);
FreeMem(KMSBase, sizeof(struct KMSBase));
}
else
Permit();
}
else
Permit();
}
/* Misc */
if (UMSBase)
{
if (SysUMSAccount)
UMSLogout(SysUMSAccount);
CloseLibrary(UMSBase);
}
if (str)
{
fputs(str, stderr);
fputs("\n", stderr);
exit(20);
}
exit(0);
}
///
/****************************
* AccessBits einlesen *
****************************
* I: --- *
* O: --- *
****************************/
/// "ReadAccBits"
VOID ReadAccBits(VOID)
{
TEXT dos[LEN_DOSPATH+1];
TEXT buff[LEN_NUMBER+LEN_ACCBITNAME+2];
UWORD n;
FILE *datei;
strcpy(dos, KMSBase->DatDir);
strcat(dos, "KMS_SYSTEM.DAT");
ObtainSemaphore(&KMSBase->SaveSem);
SystemStartups = 1;
for(n = 0; n < 32; n++)
sprintf(AccBitNames[n], "[Bit#%02d]", n+1);
if (datei = fopen(dos, "r"))
{
fgets(buff, LEN_NUMBER+2, datei);
SystemStartups = atol(buff) + 1;
for(n = 0; n < 32; n++)
{
*buff = '\0';
if (fgets(buff, LEN_ACCBITNAME+2, datei))
buff[strlen(buff)-1] = '\0';
if (!strlen(buff))
sprintf(AccBitNames[n], "[Bit#%02d]", n+1);
else
strcpy(AccBitNames[n], buff);
}
fclose(datei);
}
}
///
/***************************
* AccessBits speichern *
***************************
* I: --- *
* O: Erfolg TRUE/FALSE *
***************************/
/// "WriteAccBits"
BOOL WriteAccBits(VOID)
{
FILE *datei;
TEXT dos[LEN_DOSPATH+1];
UBYTE n;
/* Systemdaten werden nur im Besitz der Semaphore geschrieben! */
ObtainSemaphore(&KMSBase->SaveSem);
strcpy(dos, KMSBase->DatDir);
strcat(dos, "KMS_SYSTEM.DAT");
datei = fopen(dos, "w");
if (datei)
{
fprintf(datei, "%ld\n", SystemStartups);
for(n = 0; n < 32; n++)
fprintf(datei, "%s\n", AccBitNames[n]);
fclose(datei);
}
ReleaseSemaphore(&KMSBase->SaveSem);
if (datei)
return TRUE;
else
return FALSE;
}
///
/********************************
* Area in Liste suchen *
********************************
* I: Area-Index *
* O: struct AreaNode * *
********************************/
/// "SetArea"
struct AreaNode *SetArea(UWORD idx)
{
struct AreaNode *apoint;
if (!idx)
return NULL;
apoint = (struct AreaNode *)KMSBase->AreaList.mlh_Head;
if (apoint->Node.mln_Succ)
{
while (apoint->Node.mln_Succ && apoint->AreaData.ID != idx)
apoint = (struct AreaNode *)apoint->Node.mln_Succ;
if (apoint->Node.mln_Succ)
return apoint;
else
return NULL;
}
else
return NULL;
}
///
/*********************************
* Start-Area suchen *
*********************************
* I: STRPTR Pfad *
* O: struct AreaNode * *
*********************************/
/// "ResolvePath"
struct AreaNode *ResolvePath(STRPTR path)
{
struct AreaNode *current = (struct AreaNode *)KMSBase->AreaList.mlh_Head;
BOOL begin = TRUE;
TEXT token[LEN_AREANAME+1];
if (!path || !strlen(path))
return NULL;
if (!current->Node.mln_Succ)
return NULL;
TakeASem(FALSE);
if (strchr(path, '/'))
{
/* Angegebenen Pfad streng verfolgen */
/* BRETT MAUS/AMIGA */
/* BRETT /MAUS/AMIGA */
/* BRETT / */
do
{
path = PathParse(path, token);
if (!strcmp(token, "/") && begin)
{
/* Wechsel ins Hauptverzeichnis (Private Mail) */
CurrentMother = NULL;
current = SetArea(1);
}
if (begin && *path)
{
/* Wechsel ins erste Unterverzeichnis */
CurrentMother = current;
current = SetArea(current->AreaData.Daughter);
}
if (!strcmp(token, "/"))
{
/* Wechsel ins Unterverzeichnis */
if (!begin)
{
CurrentMother = current;
current = SetArea(current->AreaData.Daughter);
}
}
else
{
/* Brettname im aktuellen Verzeichnis suchen */
while(current && stricmp(current->AreaData.Name, token))
current = SetArea(current->AreaData.Next);
}
begin = FALSE;
} while(*path && current);
if (*path && !current)
CurrentMother = NULL;
DropASem();
return current;
}
else
{
/* Einzelnes Brett global suchen */
CurrentMother = NULL;
current = SetArea(1);
current = SeekAreaName(current, path);
if (current)
CurrentMother = SetArea(current->AreaData.Mother);
DropASem();
return current;
}
}
///
/*********************************************
* Nächsten Brettnamen aus Pfadangabe ziehen *
*********************************************
* I: Pfadstring, Tokenbuffer *
* O: Modifizierter Pfadstring *
*********************************************/
/// "PathParse"
STRPTR PathParse(STRPTR string, STRPTR tok)
{
UWORD n = 0;
*tok = '\0';
if (*string == '/')
{
tok[0] = *string;
tok[1] = '\0';
return ++string;
}
while(*string && *string != '/')
{
tok[n++] = *string;
string++;
}
tok[n] = '\0';
return string;
}
///
/*******************************************
* Area mit bestimmtem Namen global suchen *
*******************************************
* I: Start-Area, Name *
* O: Gefundene Area oder NULL *
*******************************************/
/// "SeekAreaName"
struct AreaNode *SeekAreaName(struct AreaNode *current, STRPTR name)
{
BOOL goon = TRUE;
BOOL stop = FALSE;
TakeASem(FALSE);
while(current && goon)
{
if (current->AreaData.Daughter && !stop)
{
current = SetArea(current->AreaData.Daughter);
stop = FALSE;
}
else if (current->AreaData.Next)
{
current = SetArea(current->AreaData.Next);
stop = FALSE;
}
else
{
current = SetArea(current->AreaData.Mother);
stop = TRUE;
}
if (current && (!stop || !current->AreaData.Mother) && !stricmp(current->AreaData.Name, name))
goon = FALSE;
}
DropASem();
return current;
}
///
/*******************************************
* UMS-MsgBase-Namen global suchen *
*******************************************
* I: gesuchte Area *
* O: AreaNode *
*******************************************/
/// "AreaSearch"
struct AreaNode *AreaSearch(STRPTR name)
{
struct AreaNode *apoint;
TakeASem(FALSE);
apoint = (struct AreaNode *)KMSBase->AreaList.mlh_Head;
while(apoint->Node.mln_Succ)
{
if (!stricmp(name, apoint->AreaData.MBName))
{
DropASem();
return apoint;
}
apoint = apoint->Node.mln_Succ;
}
DropASem();
return NULL;
}
///
/********************************
* Neue Area einhängen *
********************************
* I: struct AreaNode * *
* O: LONG *
********************************/
/// "InsertArea"
LONG InsertArea(struct AreaNode *newan)
{
LONG index = 0;
if (!CurrentMother->AreaData.Daughter)
{
/* Neue erste Tochter */
CurrentMother->AreaData.Daughter = newan->AreaData.ID;
newan->AreaData.Mother = CurrentMother->AreaData.ID;
newan->AreaData.Next = 0;
CurrentArea = newan;
return 0;
}
else
{
/* Weitere Tochter einsortieren */
struct AreaNode *daughter, *predaughter;
daughter = SetArea(CurrentMother->AreaData.Daughter);
predaughter = NULL;
if (CurrentArea)
{
/* Nach der aktuellen Area einsortieren */
while(daughter && daughter != CurrentArea)
{
index++;
predaughter = daughter;
if (daughter->AreaData.Next)
daughter = SetArea(daughter->AreaData.Next);
else
daughter = NULL;
}
}
else
{
/* Alphabetisch einsortieren */
while(daughter && stricmp(newan->AreaData.Name, daughter->AreaData.Name) != -1)
{
index++;
predaughter = daughter;
if (daughter->AreaData.Next)
daughter = SetArea(daughter->AreaData.Next);
else
daughter = NULL;
}
}
newan->AreaData.Mother = CurrentMother->AreaData.ID;
if (!predaughter)
{
/* Neue Area ist die erste */
newan->AreaData.Next = daughter->AreaData.ID;
CurrentMother->AreaData.Daughter = newan->AreaData.ID;
}
else if (!daughter)
{
/* Neue Area ist die letzte */
predaughter->AreaData.Next = newan->AreaData.ID;
newan->AreaData.Next = 0;
}
else
{
/* Neue Area zwischen predaughter und daughter einhängen */
predaughter->AreaData.Next = newan->AreaData.ID;
newan->AreaData.Next = daughter->AreaData.ID;
}
CurrentArea = newan;
return index;
}
}
///
/********************************
* Area aus Arealiste entfernen *
********************************
* I: struct AreaNode * *
* O: --- *
********************************/
/// "RemoveArea"
VOID RemoveArea(struct AreaNode *delan)
{
/* Wenn zu löschendes Brett erstes Tochterbrett ist, */
/* dann Mutter auf nächste Tochter einstimmen ;-) */
if (delan->AreaData.ID == CurrentMother->AreaData.Daughter)
{
if (delan->AreaData.Next)
CurrentMother->AreaData.Daughter = delan->AreaData.Next;
else
CurrentMother->AreaData.Daughter = 0;
}
/* Wenn zu löschendes Brett nicht einziges Unterbrett, */
/* dann "Next"-Zeiger aktualisieren */
if (CurrentMother->AreaData.Daughter)
{
struct AreaNode *tempan = NULL;
struct AreaNode *prean = NULL;
tempan = SetArea(CurrentMother->AreaData.Daughter);
while(tempan && tempan != delan)
{
prean = tempan;
if (tempan->AreaData.Next)
tempan = SetArea(tempan->AreaData.Next);
else
tempan = NULL;
}
if (prean && tempan == delan)
prean->AreaData.Next = delan->AreaData.Next;
}
}
///
/********************************
* Areas ohne Mutter löschen *
********************************
* I: --- *
* O: --- *
********************************/
/// CleanUpAreaList
VOID CleanUpAreaList(VOID)
{
CurrentArea = NULL;
struct AreaNode *apoint, *next;
UWORD loops = 1;
while(loops)
{
apoint = (struct AreaNode *)KMSBase->AreaList.mlh_Head;
while(apoint->Node.mln_Succ)
{
next = apoint->Node.mln_Succ;
if (!SetArea(apoint->AreaData.Mother) && apoint->AreaData.ID != 1)
{
/* Area ist Waise, also löschen */
if (apoint->AreaData.Daughter != 0)
/* Brett hat selber Unterbretter, also muessen wir einen
weiteren Durchlauf machen */
loops++;
DeleteAN(apoint);
}
apoint = next;
}
loops--;
}
}
///
/********************************
* KMSBase besorgen *
********************************
* I: --- *
* O: struct KMSBase * *
********************************/
/// "GetKMSBase"
struct KMSBase *GetKMSBase(VOID)
{
STRPTR bname;
/* KMSBase erzeugen, falls nicht vorhanden */
Forbid();
if (!(KMSBase = (struct KMSBase *)FindSemaphore(KMSBASENAME)))
{
bname = AllocMem((ULONG)sizeof(KMSBASENAME)+1, MEMF_PUBLIC|MEMF_CLEAR);
if (bname)
{
strcpy(bname, KMSBASENAME);
if (KMSBase = AllocMem((ULONG)sizeof(struct KMSBase), MEMF_PUBLIC|MEMF_CLEAR))
{
KMSBase->BaseSem.ss_Link.ln_Pri = 0;
KMSBase->BaseSem.ss_Link.ln_Name = bname;
KMSBase->UserSem.ss_Link.ln_Pri = 0;
KMSBase->UserSem.ss_Link.ln_Name = NULL;
KMSBase->AreaSem.ss_Link.ln_Pri = 0;
KMSBase->AreaSem.ss_Link.ln_Name = NULL;
KMSBase->SaveSem.ss_Link.ln_Pri = 0;
KMSBase->SaveSem.ss_Link.ln_Name = NULL;
NewList((struct List *)&KMSBase->AreaList);
NewList((struct List *)&KMSBase->UserList);
AddSemaphore(&KMSBase->BaseSem);
InitSemaphore(&KMSBase->UserSem);
InitSemaphore(&KMSBase->AreaSem);
InitSemaphore(&KMSBase->SaveSem);
ObtainSemaphore(&KMSBase->BaseSem);
Permit();
UMSBase = (struct Library *)OpenLibrary(UMSNAME, 0);
if (!UMSBase)
{
Error("couldn't open ums.library.");
return NULL;
}
TEXT varbuff[32] = "";
TEXT pwbuff[32] = "";
GetVar("KMSMB", varbuff, sizeof(varbuff), NULL);
GetVar("KMSPWD", pwbuff, sizeof(pwbuff), NULL);
if (!(SysUMSAccount = UMSRLogin(varbuff, "KMS", pwbuff)))
{
Error("couldn't log into UMS.");
return NULL;
}
STRPTR string;
if (string = ReadUMSConfigTags(SysUMSAccount, UMSTAG_CfgName, "KMS.datdir", TAG_DONE))
{
KMSBase->DatDir = AllocMem((ULONG)(strlen(string)+1), MEMF_PUBLIC|MEMF_CLEAR);
if (KMSBase->DatDir)
strcpy(KMSBase->DatDir, string);
FreeUMSConfig(SysUMSAccount, string);
if (!KMSBase->DatDir)
{
Error("out of memory.");
return NULL;
}
}
else
{
KMSBase->DatDir = AllocMem((ULONG)(strlen("Data/")+1), MEMF_PUBLIC|MEMF_CLEAR);
if (KMSBase->DatDir)
strcpy(KMSBase->DatDir, "Data/");
else
{
Error("out of memory.");
return NULL;
}
}
if (string = ReadUMSConfigTags(SysUMSAccount, UMSTAG_CfgName, "KMS.userdir", TAG_DONE))
{
KMSBase->UserDir = AllocMem((ULONG)(strlen(string)+1), MEMF_PUBLIC|MEMF_CLEAR);
if (KMSBase->UserDir)
strcpy(KMSBase->UserDir, string);
FreeUMSConfig(SysUMSAccount, string);
if (!KMSBase->UserDir)
{
Error("out of memory.");
return NULL;
}
}
else
{
KMSBase->UserDir = AllocMem((ULONG)(strlen("User/")+1), MEMF_PUBLIC|MEMF_CLEAR);
if (KMSBase->UserDir)
strcpy(KMSBase->UserDir, "User/");
else
{
Error("out of memory.");
return NULL;
}
}
ReleaseSemaphore(&KMSBase->BaseSem);
ObtainSemaphoreShared(&KMSBase->BaseSem);
}
else
{
Permit();
if (bname)
FreeMem(bname, sizeof(KMSBASENAME)+1);
Error("out of memory.");
return NULL;
}
}
else
{
Permit();
Error("out of memory.");
return NULL;
}
}
else
{
Permit();
ObtainSemaphoreShared(&KMSBase->BaseSem);
}
/* Arealiste einlesen oder anlegen, falls nicht vorhanden */
if (!ReadAreaList())
{
InitAreaFile();
if (!ReadAreaList())
{
Error("couldn't create or read area file.");
return NULL;
}
}
ReadAccBits();
return KMSBase;
}
///
/***************************************
* Pfad-String konstruieren *
***************************************
* I: STRPTR *
* O: --- *
***************************************/
/// "CreatePath"
VOID CreatePath(STRPTR path)
{
struct AreaNode *apoint;
TEXT merk[LEN_KMSPATH+1];
apoint = CurrentArea;
if (!apoint)
{
apoint = CurrentMother;
if (!apoint)
{
*path = '\0';
return;
}
}
strcpy(path, apoint->AreaData.Name);
if (!CurrentArea)
strcat(path, "/");
while(apoint && apoint->AreaData.Mother && strlen(path) < LEN_KMSPATH)
{
apoint = SetArea(apoint->AreaData.Mother);
strcpy(merk, path);
if (apoint && apoint->AreaData.ID != 1)
strcpy(path, apoint->AreaData.Name);
else
*path = '\0';
strcat(path, "/");
strncat(path, merk, LEN_KMSPATH - strlen(merk));
path[LEN_KMSPATH] = '\0';
}
}
///
/***************************************
* Pfad-String aktualisieren *
***************************************
* I: --- *
* O: --- *
***************************************/
/// "UpdatePath"
VOID UpdatePath(VOID)
{
CreatePath(PathString);
/*
set(ST_Path, MUIA_String_Contents, PathString);
*/
set(ST_Path, MUIA_Text_Contents, PathString);
}
///
/********************************
* String -> Großbuchstaben *
********************************
* I: STRPTR *
* O: --- *
********************************/
/// "Upper"
VOID Upper(STRPTR string)
{
if (!string)
return;
while(*string)
{
switch((UBYTE)*string)
{
case 'ä':
*string = 'Ä';
break;
case 'ö':
*string = 'Ö';
break;
case 'ü':
*string = 'Ü';
break;
default:
*string = toupper(*string);
}
string++;
}
}
///
/********************************
* Standardfehlerausgabe *
********************************
* I: --- *
* O: --- *
********************************/
/// "Error"
VOID Error(STRPTR errtxt)
{
if (errtxt)
{
fputs(errtxt, stderr);
fputs("\n", stderr);
}
}
///
/// "TakeASem"
VOID TakeASem(BOOL exclusive)
{
if (exclusive)
ObtainSemaphore(&KMSBase->AreaSem);
else
ObtainSemaphoreShared(&KMSBase->AreaSem);
}
///
/// "DropASem"
VOID DropASem(VOID)
{
ReleaseSemaphore(&KMSBase->AreaSem);
}
///
/// "TakeMSem"
VOID TakeMSem(BOOL exclusive)
{
if (exclusive)
ObtainSemaphore(&KMSBase->SaveSem);
else
ObtainSemaphoreShared(&KMSBase->SaveSem);
}
///
/// "DropMSem"
VOID DropMSem(VOID)
{
ReleaseSemaphore(&KMSBase->SaveSem);
}
///